home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xconq
/
help.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-09
|
15KB
|
493 lines
/* Copyright (c) 1987, 1988 Stanley T. Shebs, University of Utah. */
/* This program may be used, copied, modified, and redistributed freely */
/* for noncommercial purposes, so long as this notice remains intact. */
#pragma comment(exestr, "@(#) help.c 12.1 95/05/09 ")
/* RCS $Header: help.c,v 1.1 88/06/21 12:30:12 shebs Exp $ */
/* This file is devoted to commands and other functions related specifically */
/* to help. Almost all of the xconq help code is here. */
/* At least in X, the help window covers most of the xconq display, so */
/* total redraws are necessary. This can be slow - fix would be to do */
/* per-window redrawing only as need, and place help window to cover as few */
/* of the other windows as possible (especially world map). */
#include "config.h"
#include "misc.h"
#include "period.h"
#include "side.h"
#include "unit.h"
#include "map.h"
extern int helpwinlines;
/* Display the news file on stdout if it exists, be silent if it doesn't. */
/* (Used only during program startup.) */
maybe_dump_news()
{
FILE *fp;
make_pathname(XCONQLIB, NEWSFILE, "", spbuf);
if ((fp = fopen(spbuf, "r")) != NULL) {
while (fgets(spbuf, BUFSIZE-1, fp) != NULL) {
fputs(spbuf, stdout);
}
fclose(fp);
}
}
/* The general help command. It first lists the available commands, */
/* then a legend to map display, then the current news about xconq, then */
/* details about the period/units. Player can page screens back and forth, */
/* which explains some odd index adjusts at bottom of loop. */
x_help(side)
Side *side;
{
int i = side->reqvalue2;
char opt = side->reqch;
init_wprintf(side, NULL);
switch (opt) {
case ' ':
case 'n':
if (i < 4+period.numutypes) i++;
break;
case '-':
if (i > 0) i--;
break;
case '\014':
break; /* redraw */
default:
conceal_help(side);
/*redraw(side);*/
return;
}
switch (i) {
case 0:
command_help(side);
break;
case 1:
legend_help(side);
break;
case 2:
make_pathname(XCONQLIB, NEWSFILE, "", spbuf);
if (!show_file(side, spbuf)) {
wprintf(side, "No news is good news.");
}
break;
case 3:
describe_mapfiles(side);
break;
case 4:
describe_period(side);
break;
default:
/* i guaranteed to be in right range */
describe_utype(side, i - 5);
break;
}
ask_help_char(side);
request_input(side, NULL, x_help);
side->reqvalue2 = i;
}
/* The command proper must request a character for whether to go to next */
/* or previous screen, or to quit entirely. */
do_help(side, n)
Side *side;
int n;
{
if (reveal_help(side)) {
init_wprintf(side, NULL);
command_help(side);
ask_help_char(side);
request_input(side, NULL, x_help);
side->reqvalue2 = 0;
}
}
/* Prompt for a char from help window. */
ask_help_char(side)
Side *side;
{
char *help = "[Space bar to continue, '-' for prev, all else quits]";
draw_fg_text(side, side->help, 0, (helpwinlines-1)*side->fh, help);
}
/* Generate a legend for all the various symbols and pictures. */
/* (Does not include cursor box or tiny side numbers.) */
legend_help(side)
Side *side;
{
int t, u, tcol = 2 * side->margin + side->hw;
int spacing = side->hh + 4 * side->margin;
int offset = side->hh/4, second = 30*side->fw;
/* first column of things is constant for all periods */
draw_blast_icon(side, side->help,
side->margin, 0*spacing, 'b', side->enemycolor);
draw_fg_text(side, side->help, tcol, 0*spacing+offset, "miss");
draw_blast_icon(side, side->help,
side->margin, 1*spacing, 'c', side->enemycolor);
draw_fg_text(side, side->help, tcol, 1*spacing+offset, "hit");
draw_blast_icon(side, side->help,
side->margin, 2*spacing, 'd', side->enemycolor);
draw_fg_text(side, side->help, tcol, 2*spacing+offset, "kill");
for_all_terrain_types(t) {
char ch;
switch(side->showmode) {
case FULLHEX:
case BOTHICONS:
ch = HEX;
break;
case BORDERHEX:
ch = OHEX;
break;
case TERRICONS:
ch = ttypes[t].tchar;
break;
}
draw_hex_icon(side, side->help,
side->margin, (t+3)*spacing,
(side->monochrome ? side->fgcolor : side->hexcolor[t]),
(side->monochrome ? ttypes[t].tchar : ch));
draw_fg_text(side, side->help,
tcol, (t+3)*spacing+offset, ttypes[t].name);
}
for_all_unit_types(u) {
draw_unit_icon(side, side->help,
second, u*spacing, u, side->fgcolor);
draw_fg_text(side, side->help,
second+tcol, u*spacing+offset, utypes[u].name);
}
}
/* This command provides a short note about the current hex. It is */
/* useful as a supplement to the general help command. */
do_ident(side, n)
Side *side;
int n;
{
char view = side_view(side, side->curx, side->cury);
char t = terrain_at(side->curx, side->cury);
Side *side2;
if (view == UNSEEN) {
notify(side, "You see unexplored territory");
} else if (view == EMPTY) {
notify(side, "You see unoccupied %s", ttypes[t].name);
} else {
side2 = side_n(vside(view));
notify(side, "You see a %s %s (in the %s)",
(side2 == NULL ? "neutral" : side2->name),
utypes[vtype(view)].name, ttypes[t].name);
}
}
/* Dump out the characteristics of a single unit type. This works by */
/* jumping into the help loop, so all the other types can be looked at also. */
x_unit_info(side)
Side *side;
{
int u;
if ((u = find_unit_char(side->reqch)) >= 0) {
if (u != NOTHING) {
if (reveal_help(side)) {
init_wprintf(side, NULL);
describe_utype(side, u);
ask_help_char(side);
request_input(side, NULL, x_help);
side->reqvalue2 = u;
}
}
clear_prompt(side);
} else {
request_input(side, NULL, x_unit_info);
}
}
/* The command proper just prompts and issues the request. */
do_unit_info(side, n)
Side *side;
int n;
{
ask_unit_type(side, "Details on which unit type?", NULL);
request_input(side, NULL, x_unit_info);
}
/* Spit out all the general period parameters in a readable fashion. */
describe_period(side)
Side *side;
{
int u, r, t, i;
wprintf(side, "This period is named \"%s\".", period.name);
wprintf(side, "");
wprintf(side,
"It includes %d unit types, %d resource types, and %d terrain types.",
period.numutypes, period.numrtypes, period.numttypes);
wprintf(side, "First unit type is %s, first product type is %s.",
(period.firstutype == NOTHING ? "none" :
utypes[period.firstutype].name),
(period.firstptype == NOTHING ? "none" :
utypes[period.firstptype].name));
wprintf(side, "");
wprintf(side,
"Countries are %d hexes across, between %d and %d hexes apart.",
period.countrysize, period.mindistance, period.maxdistance);
wprintf(side, "Known area is %d hexes across.", period.knownradius);
wprintf(side, "Default scale is %d km/hex.", period.scale);
if (period.allseen)
wprintf(side, "All units are always seen by all sides.");
wprintf(side, "");
if (period.counterattack)
wprintf(side, "Defender always gets a counter-attack.");
else
wprintf(side, "Defender does not get a counter-attack.");
wprintf(side, "Neutral units add %d%% to defense, hit over %d is a nuke.",
period.neutrality, period.nukehit);
if (period.efficiency > 0)
wprintf(side, "Unit recycling is %d%% efficient.", period.efficiency);
wprintf(side, "");
for_all_terrain_types(t) {
wprintf(side, "Terrain: %c %s (%s)",
ttypes[t].tchar, ttypes[t].name, ttypes[t].color);
}
wprintf(side, "");
for_all_resource_types(r) {
wprintf(side, "Resource: %c %s (%s)",
' ', rtypes[r].name, rtypes[r].help);
}
wprintf(side, "");
for_all_unit_types(u) {
wprintf(side, "Unit: %c %s (%s)",
utypes[u].uchar, utypes[u].name, utypes[u].help);
}
wprintf(side, "");
if (period.notes != NULL) {
for (i = 0; period.notes[i] != NULL; ++i) {
wprintf(side, "%s", period.notes[i]);
}
}
}
/* Full details on the given type of unit. This may be used either for */
/* online help or for building a descriptive file. The icon will only */
/* show up for online help, otherwise the display calls have no effect. */
describe_utype(side, u)
Side *side;
int u;
{
int r, t, u2;
wprintf(side, " '%c' %s (territory value %d)",
utypes[u].uchar, utypes[u].name, utypes[u].territory);
wprintf(side, " %s", utypes[u].help);
if (utypes[u].bitmapname != NULL)
wprintf(side, " bitmap \"%s\"", utypes[u].bitmapname);
else
wprintf(side, "");
draw_hex_icon(side, side->help, side->margin, side->margin,
side->fgcolor, HEX);
draw_unit_icon(side, side->help, side->margin, side->margin,
u, side->bgcolor);
wprintf(side, "Init: %d in country, %d/10000 hexes density, %s.",
utypes[u].incountry, utypes[u].density,
(utypes[u].named ? "named" : "unnamed"));
wprintf(side, "Maximum speed %d hexes/turn, %d%% under control. %s %s",
utypes[u].speed, utypes[u].control,
(utypes[u].onemove ? "(auto)" : ""),
(utypes[u].jumpmove ? "(jumps)" : ""));
wprintf(side, "%d HP, crippled at %d HP, chance to retreat %d%%.",
utypes[u].hp, utypes[u].crippled, utypes[u].retreat);
wprintf(side, "%d%% extra for start up, %d%% extra for R&D.",
utypes[u].startup, utypes[u].research);
wprintf(side, "%d extra moves used up by an attack.",
utypes[u].hittime);
wprintf(side,
"%d%% to succumb to siege, %d%% to revolt, attrition damage %d HP.",
utypes[u].siege, utypes[u].revolt, utypes[u].attdamage);
if (utypes[u].seerange == 1) {
wprintf(side, "Chance to see others %d%%.", utypes[u].seebest);
} else {
wprintf(side, "Chance to see %d%% at 1 hex, to %d%% at %d hexes.",
utypes[u].seebest, utypes[u].seeworst, utypes[u].seerange);
}
wprintf(side, "Own visibility is %d.", utypes[u].visibility);
if (utypes[u].volume > 0 || utypes[u].holdvolume > 0)
wprintf(side, "Volume is %d, volume of hold is %d.",
utypes[u].volume, utypes[u].holdvolume);
wprintf(side, "%s %s",
(utypes[u].changeside ? "Can be made to change sides." : ""),
(utypes[u].disband ? "Can be disbanded and sent home." : ""));
wprintf(side, "%s %s",
(utypes[u].maker ? "Builds units all the time." : ""),
(utypes[u].selfdestruct ? "Hits by self-destruction." : ""));
wprintf(side, "");
wprintf(side, "%s",
" Resource ToBui Prod Store Eats ToMov Hits HitBy");
wprintf(side, "%s",
" (0) (0) (0) (0) (0) (0) (0)");
for_all_resource_types(r) {
sprintf(spbuf, "%10s: ", rtypes[r].name);
append_number(spbuf, utypes[u].tomake[r], 0);
append_number(spbuf, utypes[u].produce[r], 0);
append_number(spbuf, utypes[u].storage[r], 0);
append_number(spbuf, utypes[u].consume[r], 0);
append_number(spbuf, utypes[u].tomove[r], 0);
append_number(spbuf, utypes[u].hitswith[r], 0);
append_number(spbuf, utypes[u].hitby[r], 0);
wprintf(side, "%s", spbuf);
}
wprintf(side, "");
wprintf(side, "%s",
" Terrain Slowed Rand% Hide% Defn% Prod% Attr% Acdn%");
wprintf(side, "%s",
" (-) (0) (0) (0) (0) (0) (0)");
for_all_terrain_types(t) {
sprintf(spbuf, "%10s: ", ttypes[t].name);
append_number(spbuf, utypes[u].moves[t], -1);
append_number(spbuf, utypes[u].randommove[t], 0);
append_number(spbuf, utypes[u].conceal[t], 0);
append_number(spbuf, utypes[u].defense[t], 0);
append_number(spbuf, utypes[u].productivity[t], 0);
append_number(spbuf, utypes[u].attrition[t], 0);
append_number(spbuf, utypes[u].accident[t], 0);
wprintf(side, "%s", spbuf);
}
wprintf(side, "");
wprintf(side, "%s%s",
" Hit% Damg Cap% Guard Pro%",
" Holds Enter Leave Mob% Bridg Build Fix");
wprintf(side, "%s%s",
" (0) (0) (0) (0) (0)",
" (0) (1) (0) (100) (0) (0) (0)");
for_all_unit_types(u2) {
sprintf(spbuf, "%c: ", utypes[u2].uchar);
append_number(spbuf, utypes[u].hit[u2], 0);
append_number(spbuf, utypes[u].damage[u2], 0);
append_number(spbuf, utypes[u].capture[u2], 0);
append_number(spbuf, utypes[u].guard[u2], 0);
append_number(spbuf, utypes[u].protect[u2], 0);
append_number(spbuf, utypes[u].capacity[u2], 0);
append_number(spbuf, utypes[u].entertime[u2], 1);
append_number(spbuf, utypes[u].leavetime[u2], 0);
append_number(spbuf, utypes[u].mobility[u2], 100);
append_number(spbuf, utypes[u].bridge[u2], 0);
append_number(spbuf, utypes[u].make[u2], 0);
append_number(spbuf, utypes[u].repair[u2], 0);
wprintf(side, "%s", spbuf);
}
wprintf(side, "");
}
/* A simple table-printing utility. Blanks out default values so they don't */
/* clutter the table. */
append_number(buf, value, dflt)
char *buf;
int value, dflt;
{
if (value != dflt) {
sprintf(tmpbuf, "%5d ", value);
strcat(buf, tmpbuf);
} else {
strcat(buf, " ");
}
}
/* Dump assorted information into files, so they can be studied at leisure, */
/* or by people with screens too small for online help. */
do_printables(side, n)
Side *side;
int n;
{
int u;
init_wprintf(side, CMDFILE);
command_help(side);
finish_wprintf();
notify(side, "Dumped commands to \"%s\".", CMDFILE);
init_wprintf(side, PARMSFILE);
describe_period(side);
for_all_unit_types(u) {
wprintf(side, "--------------------------------------------------");
wprintf(side, "");
describe_utype(side, u);
wprintf(side, "");
}
finish_wprintf();
notify(side, "Dumped period data to \"%s\".", PARMSFILE);
dump_view(side);
notify(side, "Dumped current view to \"%s\".", VIEWFILE);
}
/* Put the current view into a file. */
dump_view(side)
Side *side;
{
char ch1, ch2;
int x, y, i, view, vs;
Side *side2;
FILE *fp;
if ((fp = fopen(VIEWFILE, "w")) != NULL) {
for (y = world.height-1; y >= 0; --y) {
for (i = 0; i < y; ++i) fputc(' ', fp);
for (x = 0; x < world.width; ++x) {
view = side_view(side, x, y);
if (view == UNSEEN) {
ch1 = ch2 = ' ';
} else if (view == EMPTY) {
ch1 = ttypes[terrain_at(x, y)].tchar;
ch2 = (side->showmode == BORDERHEX ? ' ' : ch1);
} else {
ch1 = utypes[vtype(view)].uchar;
vs = vside(view);
side2 = side_n(vside(view));
ch2 = (side2 ? ((side == side2) ? ' ' : vs + '0') : '`');
}
fputc(ch1, fp);
fputc(ch2, fp);
}
fprintf(fp, "\n");
}
} else {
notify(side, "Can't open \"%s\"!!", VIEWFILE);
}
}
/* This kicks in on a unit type prompt. Just give barest details, rely */
/* on general help for full unit descriptions. This could be spiffier */
/* and use the help window, but getting the interaction right is just too */
/* hard... */
help_unit_type(side)
Side *side;
{
int u;
for_all_unit_types(u) {
if (side->bvec[u]) {
notify(side, " %c %s; %s",
utypes[u].uchar, utypes[u].name, utypes[u].help);
}
}
}